package com.yiqiu.common.core.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 字符串工具
 *
 * @author weiyi
 */
public class StringUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(StringUtils.class);

    /** 空字符串 */
    private static final String NULLSTR = "";

    /** 下划线 */
    private static final char SEPARATOR = '_';

    /** 星号 */
    private static final char ASTERISK = '*';


    /**
     * 判断对象是否为空
     * @param str
     * @return true为空，false为非空
     */
    public static boolean isNull(Object str) {
        return str == null;
    }
    /**
     * 判断对象是否非空
     * @param str
     * @return true为非空，false为空
     */
    public static boolean isNotNull(Object str) {
        return str != null;
    }

    /**
     * 判断对象数组是否为空
     * @param arr
     * @return
     */
    public static boolean isEmpty(Object[] arr) {
        return isNull(arr) || arr.length == 0;
    }
    /**
     * 判断对象数组是否非空
     * @param arr
     * @return
     */
    public static boolean isNotEmpty(Object[] arr) {
        return !isEmpty(arr);
    }



    /**
     * 判断一个Collection是否为空， 包含List，Set，Queue
     * 
     * @param coll 要判断的Collection
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Collection<?> coll)
    {
        return isNull(coll) || coll.isEmpty();
    }

    /**
     * * 判断一个Collection是否非空，包含List，Set，Queue
     * 
     * @param coll 要判断的Collection
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Collection<?> coll)
    {
        return !isEmpty(coll);
    }



    /**
     * 判断字符串是否为空
     * @param str 输入字符串
     * @return 真为空，假为非空
     */
    public static boolean isEmpty(String str) {
        return isNull(str) || NULLSTR.equals(str.trim());
    }


    /**
     * 判断字符串是否有值
     * @param str 输入字符串
     * @return 真为有值，假为空
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 去除首尾空格
     * @param str 输入字符串
     * @return 去除首尾空格后的字符串，如果输入为空则返回null
     */
    public static String trim(String str) {
        if (isEmpty(str)) {
            LOGGER.error("字符串为空，不做处理");
            return null;
        }
        return str.trim();
    }

    /**
     * 首字母大写转换
     * 例如: "hello" -> "Hello"
     *
     * @param str 输入字符串
     * @return 首字母大写的字符串, 如果输入为null则返回null
     */
    public static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        // 如果第一个字符已经是大写,直接返回原字符串
        if (Character.isUpperCase(str.charAt(0))) {
            return str;
        }
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }

    /**
     * 将字符串转换为大写
     *
     * @param str 输入字符串
     * @return 转换后的大写字符串, 如果输入为null则返回null
     */
    public static String upperCase(String str) {
        return str == null ? null : str.toUpperCase();
    }

    /**
     * 下划线命名转换为驼峰命名
     * 例如: "hello_world" -> "helloWorld"
     * "user_name" -> "userName"
     *
     * @param str 下划线命名的字符串
     * @return 驼峰命名的字符串, 如果输入为null则返回null
     */
    public static String toCamelCase(String str) {

        if (str == null || str.isEmpty()) {
            return str;
        }


        // 先转换为小写
        str = str.toLowerCase();
        StringBuilder sb = new StringBuilder(str.length());
        boolean upperCase = false;

        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);

            if (c == '_') {
                upperCase = true;
            } else {
                if (upperCase) {
                    sb.append(Character.toUpperCase(c));
                    upperCase = false;
                } else {
                    sb.append(c);
                }
            }
        }

        return sb.toString();
    }
    /**
     * 安全的字符串截取
     * 截取从start开始到end之间所有字符（包函start和end），允许输入负数，如-1就是最后一位字符，-2就是倒数第二位字符
     * @param str 需要裁切的字符串
     * @param start 开始截止位置
     * @param end 停止截止位置
     * @return 截取后的字符串
     */
    public static String subString(String str, int start, int end) {
        if (isEmpty(str)) {
            LOGGER.error("被截取的字符串为空");
            return str;
        }
        if (Math.abs(start)> str.length()) {
            LOGGER.error("Start索引超出限制");
            return str;
        }
        if (Math.abs(end)> str.length()) {
            LOGGER.error("End索引超出限制");
            return str;
        }
        if (start < 0) {
            start = str.length() + start;
        }
        if (end < 0) {
            end = str.length() + end;
        }
        return str.substring(start, end);
    }

    /**
     * 是否包含指定字符串
     * @param str 查询字符串
     * @param strs 子字符串
     * @return 真为包含，假为不包含
     */
    public static boolean containsAny(String str, String... strs) {
        if (isEmpty(str)) {
            return false;
        }
        for (String s : strs) {
            if (s.equals(str)) {
                return true;
            }
            if (str.contains(s)) {
                return true;
            }
        }
        return false;
    }
    /**
     * 是否包含指定字符串-忽略大小写
     * @param str 查询字符串
     * @param strs 子字符串
     * @return 真为包含，假为不包含
     */
    public static boolean containsAnyIgnoreCase(String str, String... strs) {
        if (isEmpty(str)) {
            return false;
        }
        for (String s : strs) {
            if (str.equalsIgnoreCase(s)) {
                return true;
            }
            String tempSub = s.toLowerCase();
            String tempStr = str.toLowerCase();

            if (tempStr.contains(tempSub)) {
                return true;
            }
        }
        return false;
    }


    /**
     *查找子串位置
     * @param str 查询字符串
     * @param subStr 子字符串
     * @return 子串在字符串中的位置，如果未找到或字符串为空则返回-1
     */
    public static long indexOf(String str, String subStr) {
        if (isEmpty(str)) {
            LOGGER.error("查询字符串为空");
            return -1;
        }
        if (containsAny(str, subStr)) {
           return str.indexOf(subStr);
        }
        return -1;
    }
    /**
     * 替换字符串
     * @param str 查询字符串
     * @param oldPattern 被替换的字符串
     * @param newPattern 替换的字符串
     * @return 替换后的字符串
     */
    public static String replace(String str, String oldPattern, String... newPattern) {
        if (isEmpty(str) || isEmpty(oldPattern)|| isEmpty(newPattern)) {
            return null;
        }
        str = str.replaceAll(oldPattern, Arrays.toString(newPattern));
        return str;
    }
    /**
     * 删除指定字符串或字符串数组
     * @param str 被操作字符串字符串
     * @param strs 要删除的字符串数组
     * @return 删除后的字符串
     */
    public static String remove(String str, String... strs) {
        if (isEmpty(str) || isEmpty(strs)) {
            return null;
        }
        for (String s : strs) {
            str = str.replaceAll(s, "");
        }
        return str;
    }

    /**
     * 删除指定位置的字符
     * @param str 被操作字符串字符串
     * @param index 要删除的位置
     * @return 删除后的字符串
     */
    public static String remove(String str, int index) {
        if (isEmpty(str) || index < 0) {
            return null;
        }
        return str.substring(0, index) + str.substring(index + 1);
    }

    /**
     * 从源字符串中移除指定的字符(移除所有匹配项)
     * 例如: remove("hello", 'l') -> "heo"
     * @param source 源字符串
     * @param remove 要移除的字符
     * @return 处理后的字符串,如果输入为null则返回null
     */
    public static String remove(String source, char remove) {
        if (isEmpty(source)) {
            return source;
        }
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < source.length(); i++) {
            if (source.charAt(i) != remove) {
                builder.append(source.charAt(i));
            }
        }
        return builder.toString();
    }
    /**
     * 从源字符串中移除指定范围的字符
     * 例如: remove("hello", 1, 3) -> "ho"
     *
     * @param source 源字符串
     * @param start 起始位置(包含)
     * @param end 结束位置(不包含)
     * @return 处理后的字符串,如果输入为null则返回null,如果范围参数越界则返回原字符串
     */
    public static String remove(String source, int start, int end) {
        if (isEmpty(source)) {
            return source;
        }

        if (start < 0 || end > source.length() || start > end) {
            return source;
        }

        return source.substring(0, start) + source.substring(end);
    }

    /**
     * 将字符串按照指定的分隔符进行分割
     * 例如: split("hello,world", ",") -> ["hello", "world"]
     *      split("a:b;c", ":", ";") -> ["a", "b", "c"]
     *
     * @param source 要分割的源字符串
     * @param regex 一个或多个分隔符
     * @return 分割后的字符串列表，如果源字符串为空则返回null，如果没有分隔符则返回包含原字符串的单元素列表
     */
    public static List<String> split(String source, String... regex) {
        if (isEmpty(source)) {
            return null;
        }
        if (regex == null || regex.length == 0) {
            return Collections.singletonList(source);
        }
        List<String> list = new ArrayList<>();
        StringBuilder buffer = new StringBuilder();
        List<String> regexList = Arrays.asList(regex);
        for (char c : source.toCharArray()) {
            if (!regexList.contains(c + "")) {
                buffer.append(c);
            }else{
                list.add(buffer.toString());
                buffer = new StringBuilder();
            }

        }
        list.add(buffer.toString());
        return list;
    }


    /**
     * 使用指定的分隔符将字符串列表连接成一个字符串
     * 例如: join(["hello", "world"], ",") -> "hello,world"
     *
     * @param list 要连接的字符串列表
     * @param separator 分隔符
     * @return 连接后的字符串，如果列表为空则返回null
     */
    public static String join(List<String> list, String separator) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        if (list.size() == 1) {
            return String.valueOf(list.get(0));
        }
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            builder.append(list.get(i));
            if (i < list.size() - 1) {
                builder.append(separator);
            }
        }

        return builder.toString();
    }
    /**
     * 使用默认分隔符","将字符串列表连接成一个字符串
     * 例如: join(["hello", "world"]) -> "hello,world"
     *
     * @param list 要连接的字符串列表
     * @return 连接后的字符串，如果列表为空则返回null
     */
    public static String join(List<String> list) {
        return join(list, ",");
    }

    /**
     * 使用指定的分隔符将字符串数组连接成一个字符串
     * 例如: join(["hello", "world"], ";") -> "hello;world"
     *
     * @param strs 要连接的字符串数组
     * @param separator 分隔符
     * @return 连接后的字符串，如果数组为空则返回null
     */
    public static String join(String[] strs, String separator) {
        if (strs == null || strs.length == 0) {
            return null;
        }
        return join(Arrays.asList(strs), separator);
    }
    /**
     * 使用默认分隔符","将字符串数组连接成一个字符串
     * 例如: join(["hello", "world"]) -> "hello,world"
     *
     * @param strs 要连接的字符串数组
     * @return 连接后的字符串，如果数组为空则返回null
     */
    public static String join(String[] strs) {
        return join(strs, ",");
    }


    /**
     * 重复字符串指定次数
     * 例如: repeat("hello", 3) -> "hellohellohello"
     *      repeat("a", 5) -> "aaaaa"
     *
     * @param str 要重复的字符串
     * @param count 重复次数
     * @return 重复后的字符串，如果输入为空或count小于等于0则返回null
     */
    public static String repeat(String str, int count) {
        if (isEmpty(str) || count <= 0) {
            return null;
        }
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < count; i++) {
            result.append(str);
        }
        return result.toString();
    }
    

    /**
     * 格式化字符串，将占位符 {} 替换为参数值
     * 例如: format("Hello {}, your score is {}", "Tom", 95) -> "Hello Tom, your score is 95"
     *      format("Price: {} Yuan", 42.5) -> "Price: 42.5 Yuan"
     *
     * @param template 包含占位符的模板字符串
     * @param args 要替换占位符的参数值
     * @return 格式化后的字符串，如果模板为空则返回null，如果参数为空则保留占位符
     */
    public static String format(String template, Object... args) {
        if (isEmpty(template)) {
            return null;
        }
        if (isEmpty(args)) {
            return template;
        }

        StringBuilder result = new StringBuilder(template);
        int parameterIndex = 0;
        int index;
        String placeHolder = "{}";

        while ((index = result.indexOf(placeHolder)) != -1 && parameterIndex < args.length) {
            Object arg = args[parameterIndex];
            result.replace(index, index + placeHolder.length(), 
                         arg != null ? arg.toString() : "null");
            parameterIndex++;
        }

        return result.toString();
    }
    
    /**
     * 比较两个字符串是否相等
     * 例如: equals("hello", "hello") -> true
     *      equals("hello", null) -> false
     *      equals(null, null) -> true
     *      equals("Hello", "hello", true) -> true
     *
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @param ignoreCase 是否忽略大小写
     * @return 如果两个字符串相等返回true，否则返回false
     */
    public static boolean equals(String str1, String str2, boolean ignoreCase) {
        if (str1 == str2) {
            return true;
        }
        if (str1 == null || str2 == null) {
            return false;
        }
        return ignoreCase ? str1.equalsIgnoreCase(str2) : str1.equals(str2);
    }

    /**
     * 比较两个字符串是否相等（区分大小写）
     * 例如: equals("hello", "hello") -> true
     *      equals("Hello", "hello") -> false
     *
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @return 如果两个字符串相等返回true，否则返回false
     */
    public static boolean equals(String str1, String str2) {
        return equals(str1, str2, false);
    }


    /**
     * 判断字符串数组中是否存在空白字符串
     * @param strs 字符串数组
     * @return 
     */
    public static boolean isAnyBlank(String... strs) {
        boolean isAnyBlank = false;
        for (String str : strs) {
            if (isEmpty(str)) {
                isAnyBlank = true;
                break;
            }
        }
        return isAnyBlank;
    }
}
